home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998…tember: Reference Library / Dev.CD Sep 98 RL2.toast / What's New / Software Development Kits / MacOS USB DDK / Examples / PrinterClassDriver / Chooser.cp next >
Encoding:
Text File  |  1998-07-20  |  32.5 KB  |  1,140 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Chooser.cp
  3.  
  4.     Contains:    Chooser PACK code to support USB and serial printers
  5.  
  6.     Copyright:    © 1998 by Apple Computer, Inc., all rights reserved.
  7. */
  8.  
  9. #ifndef __Chooser__
  10. #include "Chooser.h"
  11. #endif
  12.  
  13. #ifndef __COMMON__
  14. #include "Common.h"
  15. #endif
  16.  
  17. #ifndef __UTILS__
  18. #include "Utils.h"
  19. #endif
  20.  
  21. #ifndef __DEVICES__
  22. #include <Devices.h>
  23. #endif
  24.  
  25. #ifndef __RESOURCES__
  26. #include <Resources.h>
  27. #endif
  28.  
  29. #ifndef __TEXTUTILS__
  30. #include <TextUtils.h>
  31. #endif
  32.  
  33. #ifndef __COMMRESOURCES__
  34. #include <CommResources.h>
  35. #endif
  36.  
  37. #ifndef __CRMSERIALDEVICES__
  38. #include <CRMSerialDevices.h>
  39. #endif
  40.  
  41. #ifndef __MIXEDMODE__
  42. #include <MixedMode.h>
  43. #endif
  44.  
  45. #ifndef __CODEFRAGMENTS__
  46. #include <CodeFragments.h>
  47. #endif
  48.  
  49. #ifndef __DIALOGS__
  50. #include <dialogs.h>
  51. #endif
  52.  
  53. #ifndef __SafeNameRegistry__
  54. #include "SafeNameRegistry.h"
  55. #endif
  56.  
  57. /******************************************************************************
  58.     Typedefs
  59.  ******************************************************************************/
  60.  
  61. // This structure is passed to AddPrintertoList (a callback routine) from
  62. // SearchForUSBPrinters. Its used to hold data which is needed to add a
  63. // printer name to the Chooser's printer list
  64. typedef struct
  65. {
  66.     ListHandle    list;            // the printer list
  67.     Cell        insertcell;        // where to insert an entry
  68.     short        modelIndex;        // index into STR# holding printer models supported
  69. } AddPrintertoListCallBackStruct, *AddPrintertoListCallBackStructPtr;
  70.  
  71. // This structure is passed to AddPorttoList (a callback routine) from
  72. // SearchForSerialPorts. Its used to hold data which is needed to add a
  73. // serial port to the Chooser's printer list
  74. typedef struct
  75. {
  76.     ListHandle    list;            // the printer list
  77.     Cell        insertcell;        // where to insert an entry
  78. } AddPorttoListCallBackStruct, *AddPorttoListCallBackStructPtr;
  79.  
  80. // typedef for callback routine used in SearchForUSBPrinters when a printer
  81. // entry is found in the name registry
  82. typedef void (*FoundUSBPrinterProcPtr) ( RegEntryID* aPrinterEntry, void* userData);
  83.  
  84. // typedef for callback routine used in SearchForSerialPorts when a port
  85. // entry is found in the name registry
  86. typedef void (*FoundSerialPortProcPtr) ( CRMSerialPtr aPort, void* userData);
  87.  
  88. /******************************************************************************
  89.     Prototypes
  90.  ******************************************************************************/
  91.  
  92. short    CountUSBPrinters(void);
  93. void    FillPrinterList( ListHandle list );
  94. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData );
  95. void    CountAPrinter( RegEntryID* aPrinterEntry, void* userData );
  96. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData );
  97.  
  98. short    CountSerialPorts(void);
  99. void    AddPorttoList( CRMSerialPtr aPort, void* userData );
  100. void    CountAPort(  CRMSerialPtr aPort, void* userData );
  101. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData);
  102.  
  103. OSErr    ShowSelection (ListHandle list, StringPtr zoneName);
  104. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum);
  105.  
  106. void    SetConnectionType(short    type);
  107. short    GetConnectionType(void);
  108. OSErr    InitPack(void);
  109.  
  110. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list );
  111. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list);
  112. Handle    GetLastSelectedUSBPrinter();
  113.  
  114. /******************************************************************************
  115.     Constants
  116.  ******************************************************************************/
  117.  
  118. #define        kHilited    0
  119. #define        kUnHilited    255
  120.  
  121. #define        kGlobalType        'wxyz'        // made up type
  122. #define        kGlobalID        128
  123.  
  124. #define        kConnectionType        'CTYP'
  125. #define        kConnectionTypeID    1000
  126.  
  127. // Possible selected types. Used in ConnectionType rsrc
  128. #define        kNone            0
  129. #define        kSerial            1
  130. #define        kUSB            2
  131.  
  132. #define     kAPortName    "\p.AIn"    // To compare input device name when searching serial devices in the Comm Tool Box's List
  133. #define        kBPortName    "\p.BIn"    // To comapre input device name when searching serial devices in the Comm Tool Box's List
  134.  
  135. #define        kPrinterNotAvailable    3100
  136. /*-----------------------------------------------------------------------------*
  137.  
  138.     SaveSelectedUSBPrinter
  139.     
  140.     Desc:        Saves the name registry path of the selected printer
  141.  
  142.     In:            - the cell of the selected printer
  143.                 - the Chooser's printer list
  144.                 - the row of the selected cell
  145.                 
  146.     Out:        true if the path was saved
  147.                 false if the path wasn't saved
  148.  
  149.     History:
  150.     
  151.     21 Apr 98    gp        Created
  152.     
  153.  *-----------------------------------------------------------------------------*/
  154. Boolean    SaveSelectedUSBPrinter( Cell selectedCell, ListHandle list )
  155. {
  156.     Handle        lastPrinterString=nil;    // the previous selected printer 
  157.     Str255         selectedPrinterName;    // name of the selected printer
  158.     Str255        modelString;    // path in name registry of printer model
  159.     Boolean        saved=false;            // was the selected printer saved properly
  160.  
  161.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  162.  
  163.     gGlobals = GetGlobalStorage();
  164.  
  165.     // Get the name of the printer that was selected out of the list
  166.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  167.     // get the last selected printer
  168.     lastPrinterString = GetLastSelectedUSBPrinter();
  169.  
  170.     // get the model path
  171.     GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+selectedCell.v) );
  172.     if( modelString[0] != 0 && lastPrinterString != nil) 
  173.     {                
  174.         Handle    tempHandle=nil;
  175.         // create the selected printer's name registry path
  176.         AppendPStr( (StringPtr) modelString, "\p:" );
  177.         AppendPStr( (StringPtr) modelString, selectedPrinterName );
  178.         
  179.         HLock( lastPrinterString );
  180.         BlockMove( modelString, *lastPrinterString, modelString[0]+1 );
  181.         HUnlock( lastPrinterString );
  182.  
  183.         // save the selected printers's name registry path
  184.         ChangedResource( lastPrinterString );
  185.         SetConnectionType( kUSB );
  186.         
  187.         WriteResource(lastPrinterString);
  188.         saved = true;
  189.     }
  190.     return saved;
  191. }
  192.  
  193. /*-----------------------------------------------------------------------------*
  194.  
  195.     GetLastSelectedUSBPrinter
  196.     
  197.     Desc:        Returns the name registry path of the last selected USB printer
  198.  
  199.     In:            None
  200.                 
  201.     Out:        Handle to a STR containing the name registry path of the last
  202.                 selected USB printer
  203.  
  204.     History:
  205.     
  206.     21 Apr 98    gp        Created
  207.     
  208.  *-----------------------------------------------------------------------------*/
  209. Handle    GetLastSelectedUSBPrinter()
  210. {
  211.     Handle            printerString=nil;    // the full path in name registry of last selected USB printer
  212.  
  213.     printerString = Get1Resource( 'STR ', kUSBPrinterPathString );
  214.     if( printerString == nil ) {
  215.         DebugStr("\pIn GetLastSelectedUSBPrinter. THIS SHOULD NEVER HAPPEN");
  216.     }
  217.     return printerString;
  218. }
  219.  
  220. /*-----------------------------------------------------------------------------*
  221.  
  222.     SaveSelectedPrinterName
  223.     
  224.     Desc:        Saves the name of the selected printer in our rsrc
  225.  
  226.     In:            - the cell of the selected printer
  227.                 - the Choosers printer list handle
  228.                 
  229.     Out:        None
  230.  
  231.     History:
  232.     
  233.     21 Apr 98    gp        Created
  234.     
  235.  *-----------------------------------------------------------------------------*/
  236. void    SaveSelectedPrinterName( Cell selectedCell, ListHandle list)
  237. {
  238.     Handle            printerString=nil;        // path in name registry of current USB printer
  239.     Str255             selectedPrinterName;            // name of the selected printer
  240.  
  241.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  242.  
  243.     // save the name of the printer
  244.     printerString = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  245.     if( selectedPrinterName[0] != 0 && printerString != nil) 
  246.     {
  247.         HLock( printerString );
  248.         BlockMove( selectedPrinterName, *printerString, selectedPrinterName[0]+1 );
  249.         HUnlock( printerString );
  250.  
  251.         // save the newly selected printer's name
  252.         ChangedResource( printerString );
  253.         WriteResource(printerString);
  254.     }
  255.  
  256. }
  257.  
  258. /*-----------------------------------------------------------------------------*
  259.  
  260.     GetConnectionType
  261.     
  262.     Desc:        Gets the connection type for the last selected printer
  263.                 from our rsrc
  264.  
  265.     In:            None
  266.                 
  267.     Out:        kNone, kSerial or kUSB
  268.  
  269.     History:
  270.     
  271.     27 Mar 98    gp        Created
  272.     
  273.  *-----------------------------------------------------------------------------*/
  274. short    GetConnectionType(void)
  275. {
  276.     Handle    connection;
  277.  
  278.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  279.     return (**(short**)connection);
  280.  
  281. }
  282.  
  283. /*-----------------------------------------------------------------------------*
  284.  
  285.     SetConnectionType
  286.     
  287.     Desc:        Saves the connection type of the selected printer in our rsrc
  288.  
  289.     In:            kNone, kSerial or kUSB
  290.                 
  291.     Out:        None
  292.     
  293.     History:
  294.     
  295.     27 Mar 98    gp        Created
  296.     
  297.  *-----------------------------------------------------------------------------*/
  298. void    SetConnectionType(short    type)
  299. {
  300.     Handle    connection;
  301.  
  302.     connection = (Handle) Get1Resource( kConnectionType, kConnectionTypeID );
  303.     (**(short**)connection) = type;
  304.     ChangedResource( connection );
  305.     WriteResource( connection );
  306. }
  307.  
  308. /*-----------------------------------------------------------------------------*
  309.  
  310.     CountAPort
  311.     
  312.     Desc:        Callback routine for CountSerialPorts. It increments the
  313.                 ptr to user data thus incrementing the count of serial ports.
  314.  
  315.     In:            - A port to a CRMSerialPtr struct
  316.                 - A ptr to user data
  317.  
  318.     Out:        None
  319.     
  320.     History:
  321.     
  322.     26 Mar 98    gp        Created
  323.     
  324.  *-----------------------------------------------------------------------------*/
  325. void    CountAPort(  CRMSerialPtr aPort, void* userData )
  326. {
  327.     // we're only interested in .ain and .bin
  328.     if ( (PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) ) ||
  329.         (PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) ))
  330.     {
  331.             *((short*) userData) +=1;
  332.     }
  333. }
  334.  
  335. /*-----------------------------------------------------------------------------*
  336.  
  337.     AddPorttoList
  338.     
  339.     Desc:        Adds a serial port the the Chooser's list. We're only interested
  340.                 in modem and printer ports
  341.  
  342.     In:            - A port to a CRMSerialPtr struct
  343.                 - A ptr to user data. This should be a ptr to a 
  344.                   AddPorttoListCallBackStruct
  345.  
  346.     Out:        None
  347.     
  348.     History:
  349.     
  350.     26 Mar 98    gp        Created
  351.     
  352.  *-----------------------------------------------------------------------------*/
  353. void    AddPorttoList( CRMSerialPtr aPort, void* userData )
  354. {
  355.     AddPorttoListCallBackStructPtr     addPortStruct=(AddPorttoListCallBackStructPtr) userData;
  356.  
  357.     // we're only interested in .ain and .bin
  358.     if ( PStrEqualCaseInsensitive((unsigned char*) kBPortName, *(aPort->inputDriverName)) )
  359.     {
  360.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  361.         LSetCell( "Printer", 7, addPortStruct->insertcell, addPortStruct->list );
  362.         addPortStruct->insertcell.v++;
  363.     }
  364.     
  365.     if ( PStrEqualCaseInsensitive((unsigned char*) kAPortName, *(aPort->inputDriverName)) )
  366.     {
  367.         LAddRow(1, addPortStruct->insertcell.v, addPortStruct->list);
  368.         LSetCell( "Modem", 5, addPortStruct->insertcell, addPortStruct->list );
  369.         addPortStruct->insertcell.v++;
  370.     }
  371. }
  372.  
  373. /*-----------------------------------------------------------------------------*
  374.  
  375.     CountSerialPorts
  376.     
  377.     Desc:        Returns the number of serial ports
  378.  
  379.     In:            None
  380.                 
  381.     Out:        The number of serial ports
  382.     
  383.     History:
  384.     
  385.     26 Mar 98    gp        Created
  386.     
  387.  *-----------------------------------------------------------------------------*/
  388. short    CountSerialPorts(void)
  389. {
  390.     short    numberOfPorts=0;
  391.  
  392.     SearchForSerialPorts( (FoundSerialPortProcPtr) &CountAPort, &numberOfPorts );
  393.  
  394.     return numberOfPorts;
  395. }
  396.  
  397. /*-----------------------------------------------------------------------------*
  398.  
  399.     SearchForSerialPorts
  400.     
  401.     Desc:        Searchs for serial ports on this machine
  402.  
  403.     In:            - A callback routine which gets called when a printer is found
  404.                 - A ptr to user data
  405.  
  406.     Out:        None
  407.     
  408.     History:
  409.     
  410.     26 Mar 98    gp        Created
  411.     
  412.  *-----------------------------------------------------------------------------*/
  413. void    SearchForSerialPorts(FoundSerialPortProcPtr callback, void* userData)
  414. {
  415.     CRMErr                theErr;                // comm rsrc manager error
  416.     CRMRec                commRec;            // communications resource manager record
  417.     CRMRecPtr            commRecPtr;            // ptr to a communication resource record in the queue
  418.     CRMSerialPtr        commRecSerialPtr;    // ptr to serial record inside comm resource record
  419.     long            curSerialDeviceID = 0;     // initially set to zero, so we get all serial devices
  420.  
  421.     theErr = InitCRM(); // Initialize the Communications Resource Manager
  422.  
  423.     // now search for serial devices
  424.     while (theErr == noErr)
  425.     {
  426.         commRec.crmDeviceType = crmSerialDevice; // look for serial devices
  427.         commRec.crmDeviceID = curSerialDeviceID; // look for a device number greater than curSerialDeviceID
  428.     
  429.         commRecPtr = &commRec;
  430.         commRecPtr = CRMSearch(commRecPtr);    // Search  queue for each serial device
  431.     
  432.         if (commRecPtr != nil)
  433.         {
  434.             // get the Serial record pointer
  435.             commRecSerialPtr = (CRMSerialPtr)(*commRecPtr).crmAttributes;
  436.             
  437.             callback( commRecSerialPtr, userData);    // found a port
  438.             
  439.             // Set device ID for next search
  440.             curSerialDeviceID = (*commRecPtr).crmDeviceID;
  441.         }
  442.         else
  443.         {
  444.             theErr = 1; // game over, no more serial devices
  445.         }
  446.     }
  447. }
  448.  
  449. /*-----------------------------------------------------------------------------*
  450.  
  451.     SearchForUSBPrinters
  452.     
  453.     Desc:        Searches thru a printer model entry in the name registry
  454.                 looking for a model's printers. When one is found a call is 
  455.                 issued to the clients callback routine for further processing
  456.  
  457.     In:            - A pstring full path in the name registry of a printer model
  458.                 - A callback routine which gets called when a printer is found
  459.                 - A ptr to user data
  460.                 
  461.     Out:        None
  462.     
  463.     History:
  464.     
  465.     24 Feb 98    gp        Created
  466.     
  467.  *-----------------------------------------------------------------------------*/
  468. void    SearchForUSBPrinters( StringPtr modelPath, FoundUSBPrinterProcPtr callback, void* userData )
  469. {
  470.  
  471.     RegEntryID        theModelEntry;        // the model node supported by the driver
  472.     RegEntryID        aPrinterEntry;        // a printer node in the name registry
  473.     RegEntryIterationOp iterOp;            // name registry iterator op code
  474.     RegEntryIter    printerIterator;    // used to iterate child nodes of printer model
  475.     Boolean            donePrinters    = false;    // NameRegistry param tell when we're done
  476.     OSStatus        err             = noErr;    // error from name registry calls
  477.  
  478.     // name registry only deals with c strings
  479.     p2cstr( (StringPtr) modelPath );
  480.  
  481.     // look up the node for the printer model requested
  482.     err = SafeRegistryEntryIDInit(&theModelEntry);
  483.     err = SafeRegistryCStrEntryLookup( nil, (char*) modelPath, &theModelEntry );
  484.  
  485.     if( err == noErr ) 
  486.     {
  487.         // create an iterator to look at the child nodes for our printer model entry
  488.         iterOp = kRegIterChildren;
  489.  
  490.         err = SafeRegistryEntryIterateCreate( &printerIterator );
  491.         err = SafeRegistryEntryIterateSet(&printerIterator, &theModelEntry);
  492.         
  493.         if( err == noErr )
  494.         {
  495.             // look for a model's connected printers
  496.             do
  497.             {
  498.                 err = SafeRegistryEntryIterate( &printerIterator, iterOp, &aPrinterEntry, &donePrinters );
  499.                 if( !donePrinters && err == noErr )
  500.                     callback(&aPrinterEntry, userData);    // found a printer
  501.  
  502.                 iterOp = kRegIterContinue;
  503.             } while( !donePrinters && err == noErr );
  504.             // end while for printers
  505.         }
  506.         SafeRegistryEntryIterateDispose(&printerIterator);
  507.     }
  508.  
  509.     SafeRegistryEntryIDDispose( &theModelEntry );
  510.     c2pstr( (char*) modelPath );
  511.  
  512. }
  513.  
  514. /*-----------------------------------------------------------------------------*
  515.  
  516.     CountAPrinter
  517.     
  518.     Desc:        Callback routine for CountUSBPrinters. It increments the
  519.                 ptr to user data thus incrementing the count of USB printers.
  520.  
  521.     In:            - A printer entry in the name registry
  522.                 - A ptr to user data
  523.                 
  524.     Out:        The number of USB printers in the name registry
  525.     
  526.     History:
  527.     
  528.     24 Feb 98    gp        Created
  529.     
  530.  *-----------------------------------------------------------------------------*/
  531.  
  532. void    CountAPrinter(  RegEntryID* aPrinterEntry, void* userData )
  533. {
  534.     *((short*) userData) +=1;
  535. }
  536.  
  537. /*-----------------------------------------------------------------------------*
  538.  
  539.     CountUSBPrinters
  540.     
  541.     Desc:        Returns the number of connected USB printers associated with this driver
  542.  
  543.     In:            None
  544.                 
  545.     Out:        The number of USB printers in the name registry
  546.     
  547.     History:
  548.     
  549.     24 Feb 98    gp        Created
  550.     
  551.  *-----------------------------------------------------------------------------*/
  552.  
  553. short    CountUSBPrinters()
  554. {
  555.     short            numberOfPrinters=0;    // return value for number of USB printers
  556.     Str255            modelPath;            // pstring path in a supported printer model
  557.     short            i;                    // counter
  558.  
  559.     i=1;
  560.     // read a supported printer's name registry model path
  561.     GetIndString(modelPath, kUSBModelPathString, i);
  562.     
  563.     while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  564.     {
  565.         SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &CountAPrinter, &numberOfPrinters );
  566.         i++;
  567.         // read another supported printer's name registry model path
  568.         GetIndString(modelPath, kUSBModelPathString, i);
  569.     }
  570.  
  571.     return numberOfPrinters;
  572. }
  573.  
  574. /*-----------------------------------------------------------------------------*
  575.  
  576.     AddPrintertoList
  577.     
  578.     Desc:        Adds an USB printer to the Chooser's printer list by extracting
  579.                 the name from the name registry
  580.  
  581.     In:            - A printer entry in the name registry
  582.                 - A ptr to user data. This should be a ptr to a 
  583.                   AddPrintertoListCallBackStruct 
  584.                 
  585.     Out:        The number of USB printers in the name registry
  586.     
  587.     History:
  588.     
  589.     24 Feb 98    gp        Created
  590.     
  591.  *-----------------------------------------------------------------------------*/
  592. void    AddPrintertoList( RegEntryID* aPrinterEntry, void* userData )
  593. {
  594.     OSStatus        err = noErr;        // error from name registry call
  595.     Str255            nodeName;            // the name of the printer
  596.     RegPropertyValueSize    nameSize;    // size of name buffer
  597.     AddPrintertoListCallBackStructPtr     fillListStruct=(AddPrintertoListCallBackStructPtr) userData;
  598.     USBGlobalsHandle    gGlobals=nil;    // our global data area
  599.  
  600.     gGlobals = GetGlobalStorage();
  601.  
  602.     nameSize = sizeof( nodeName );
  603.     // grab name of printer in name registyr
  604.     err = SafeRegistryPropertyGet( aPrinterEntry, "name", &nodeName, &nameSize );
  605.     
  606.     if( err == noErr ) {
  607.         // stick it in the printer list
  608.         LAddRow(1, fillListStruct->insertcell.v, fillListStruct->list);
  609.         LSetCell( nodeName, nameSize-1, fillListStruct->insertcell, fillListStruct->list );
  610.         
  611.         // save info about which model (STR#) this printer belongs to
  612.         *((**gGlobals).modelIndex+fillListStruct->insertcell.v) = fillListStruct->modelIndex;
  613.         fillListStruct->insertcell.v++;
  614.     }
  615. }
  616.  
  617. /*-----------------------------------------------------------------------------*
  618.  
  619.     FillUSBList
  620.     
  621.     Desc:        Fills the printer list with the number of USB printers
  622.  
  623.     In:            - The Chooser's printer list handle
  624.                 
  625.     Out:        None
  626.     
  627.     History:
  628.     
  629.     24 Feb 98    gp        Created
  630.     
  631.  *-----------------------------------------------------------------------------*/
  632. void    FillPrinterList( ListHandle list )
  633. {
  634.     AddPrintertoListCallBackStruct    userData;    // struct needed by callback routine
  635.     AddPorttoListCallBackStruct        userPortData;    // struct needed by callback routine
  636.     Str255        modelPath;                        // pstring path in a supported printer model
  637.     short        i;                                // counter
  638.  
  639.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  640.     
  641.     gGlobals = GetGlobalStorage();
  642.     
  643.     userPortData.insertcell.v = 0;
  644.     // if we support serial ports then list serial ports
  645.     if( (**gGlobals).supportsSerial == true ) {
  646.         userPortData.list = list;
  647.         userPortData.insertcell.h = 0;
  648.  
  649.         // add the serial ports to the chooser list
  650.         SearchForSerialPorts( (FoundSerialPortProcPtr) &AddPorttoList, (void*) &userPortData );
  651.     }
  652.  
  653.     // if we support USB then list USB printers
  654.     if( (**gGlobals).supportsUSB == true ) {
  655.         userData.list = list;
  656.         userData.insertcell.v = userPortData.insertcell.v;
  657.         userData.insertcell.h = 0;
  658.  
  659.         i=1;
  660.         // read a supported printer's name registry model path
  661.         GetIndString(modelPath, kUSBModelPathString, i);
  662.         while( (char*) modelPath[0] != 0 )        // if len is zero then no more models
  663.         {
  664.             userData.modelIndex = i;
  665.             // add the USB printers to the chooser list
  666.             SearchForUSBPrinters( modelPath, (FoundUSBPrinterProcPtr) &AddPrintertoList, (void*) &userData );
  667.             i++;
  668.             // read another supported printer's name registry model path
  669.             GetIndString(modelPath, kUSBModelPathString, i);
  670.         }
  671.     }
  672. }
  673.  
  674. /*-----------------------------------------------------------------------------*
  675.     
  676.     ShowSelection
  677.     
  678.     Desc:        Hilites the currently selected printer in the printer list
  679.  
  680.     In:            - Handle to Mac List Mgr list
  681.                 - Name of zone we are currently in
  682.                 
  683.     Out:        OS error if any
  684.     
  685.     History:
  686.     
  687.     21 Apr 98    gp        If only 1 USB printer is listed and no previous selection
  688.                         then select it. If previously selected printer is not available
  689.                         display an alert.
  690.     9  Apr 98    gp        Use hlock not hunlock. Moved foundcell outside loop
  691.     21 Mar 98    gp        Extract previously selected printer from our rsrc
  692.     24 Feb 98    gp        Created
  693.     
  694.  *-----------------------------------------------------------------------------*/
  695. OSErr    ShowSelection (ListHandle list, StringPtr zoneName)
  696. {
  697.     Cell            cell;                            // used to iterate thru printer list, shows selected cell
  698.     Str255            nameBuffer;                        // selected AT printer is on the net, search for the cell
  699.     Boolean            foundCell = false;                // found a cell with same name as selected printer
  700.     Handle            selectedPrinter;                // name of the selected printer
  701.  
  702.     Str255            modelString;                    // path in name registry of printer model
  703.     Handle            printerString;                    // the full path in name registry of selected USB printer
  704.     RegEntryID        thePrinterEntry;                // the node of the USB printer node selected
  705.     OSStatus        err             = noErr;        // err encountered when calling name registry API
  706.     short            hiliteState = kUnHilited;        // hilite state of the button
  707.     USBGlobalsHandle    gGlobals=nil;                // our global data area
  708.     short            connectionType;                    // what type of printer connection, serial or USB
  709.     
  710.     gGlobals = GetGlobalStorage();
  711.  
  712.     // get the current selected printer out of the rsrc
  713.     printerString = GetLastSelectedUSBPrinter();
  714.     if( printerString == nil ) {
  715.         return noErr;
  716.     }
  717.  
  718.     // extract printer name for use later
  719.     selectedPrinter = (Handle) Get1Resource( 'STR ', kPrinterNameString );
  720.     if(  selectedPrinter == nil)
  721.         return noErr;
  722.     HLock( selectedPrinter );
  723.  
  724.     connectionType = GetConnectionType();
  725.     switch( connectionType ) {
  726.         case kSerial:
  727.             SetPt (&cell, 0, 0);
  728.  
  729.             // look for the port
  730.             while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  731.             {
  732.                 GetNameFromCell(nameBuffer, cell, list);
  733.  
  734.                 // if it equals the name of the current cell, we found the printer
  735.                 if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  736.                     foundCell = true;
  737.                 } else
  738.                     cell.v++;
  739.             }
  740.             if( !foundCell )
  741.                 StopAlert(kPrinterNotAvailable, nil);
  742.             break;
  743.         case kUSB:
  744.             HLock( printerString );
  745.  
  746.             // name registry only deals with c strings
  747.             p2cstr( (StringPtr) *printerString );
  748.  
  749.             // check to make sure printer is still in name registry before selecting
  750.             SafeRegistryEntryIDInit(&thePrinterEntry);
  751.             err = SafeRegistryCStrEntryLookup( nil, (char*) *printerString, &thePrinterEntry );
  752.             
  753.             // clean up
  754.             c2pstr( (char*) *printerString );
  755.             HUnlock( printerString );
  756.             SafeRegistryEntryIDDispose( &thePrinterEntry );
  757.  
  758.             // if printer is no longer connected put up an alert
  759.             if( err ) {
  760.                 StopAlert(kPrinterNotAvailable, nil);
  761.             } else {
  762.                 // since user could have connected or disconnect other printers from USB bus
  763.                 // we need to find the exact place in the list and hilite it
  764.  
  765.                 SetPt (&cell, 0, 0);
  766.  
  767.                 // loop through all the printers in the list seeing if there is a
  768.                 // match for the driver's selected printer
  769.                 while ( (!foundCell) && (cell.v < (*list)->dataBounds.bottom) )
  770.                 {
  771.                     GetNameFromCell(nameBuffer, cell, list);
  772.  
  773.                     // If the name is one of our reserved rows and
  774.                     // it equals the name of the current cell, we found a possible printer
  775.                     
  776.                     if ( EqualString( (StringPtr) *selectedPrinter, nameBuffer, true, true) ) {
  777.  
  778.                         // create name registry full path for this printer and compare it
  779.                         // to the one thats stored in our rsrc
  780.                         
  781.                         // get the printers model
  782.                         GetIndString(modelString, kUSBModelPathString, *((**gGlobals).modelIndex+cell.v) );
  783.                         if( modelString[0] != 0 ) 
  784.                         {
  785.                             // create the path
  786.                             AppendPStr( (StringPtr) modelString, "\p:" );
  787.                             AppendPStr( (StringPtr) modelString, nameBuffer );
  788.                             // check to see if its the same
  789.                             HLock( printerString );
  790.                             if ( EqualString( modelString, (StringPtr) *printerString, true, true) )
  791.                                 foundCell = true;
  792.                             HUnlock( printerString );
  793.                         }
  794.                     }
  795.  
  796.                     if (!foundCell)
  797.                         cell.v++;
  798.                 } // end while
  799.             } // end else
  800.             break;
  801.         default:
  802.             break;
  803.     }
  804.     HUnlock( selectedPrinter );
  805.  
  806.     // if this is our first time and only 1 entry in the list and its USB then select it
  807.     if( ((**gGlobals).supportsUSB == true) && !foundCell && 
  808.         ((*list)->dataBounds.bottom == 1) && ((**gGlobals).numberOfUSBPrinters == 1) ) 
  809.     {
  810.         if( printerString != nil && (**printerString) == 0x0) {
  811.             SetPt(&cell, 0, 0);        // select the 1st cell
  812.  
  813.             if( SaveSelectedUSBPrinter( cell, list ) ) {
  814.                 // save the name of the printer
  815.                 SaveSelectedPrinterName( cell, list );
  816.                 foundCell = true;
  817.             }
  818.         }
  819.     }
  820.  
  821.     // now hilite the selection
  822.     if (foundCell)
  823.     {
  824.         LSetSelect(true, cell, list);
  825.         hiliteState = kHilited;
  826.     }
  827.  
  828.  
  829.     return noErr;
  830. }
  831.  
  832. /*-----------------------------------------------------------------------------*
  833.  
  834.     Select
  835.     
  836.     Desc:        Save the selected printers name and name registry path in our rsrc
  837.  
  838.     In:            - Handle to Mac List Mgr list
  839.                 - Name of zone we are currently in
  840.                 - the row Chooser thinks we should select.
  841.                 
  842.     Out:        OS error if any
  843.     
  844.     History:
  845.     
  846.     21 Mar 98    gp        Save printer name in our rsrc
  847.     24 Feb 98    gp        Created
  848.  
  849. *-----------------------------------------------------------------------------*/
  850. OSErr    Select (ListHandle list, StringPtr zoneName, long rowNum)
  851. {
  852.     
  853.     Str255            modelString;            // path in name registry of printer model
  854.     Handle            printerString=nil;        // path in name registry of current USB printer
  855.     Cell            selectedCell;            // for list processing
  856.     Str32            selectedPrinterName;    // select printer in list
  857.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  858.  
  859.     gGlobals = GetGlobalStorage();
  860.  
  861.     // Find out which row was selected
  862.     SetPt (&selectedCell, 0, 0);
  863.     LGetSelect (true, &selectedCell, list);
  864.  
  865.     // Get the name of the printer that was selected out of the list
  866.     GetNameFromCell (selectedPrinterName, selectedCell, list);
  867.  
  868.     // if nothing selected leave
  869.     if( selectedPrinterName[0] == 0 )
  870.         return noErr;
  871.  
  872.     // serial port selected so just clear the USB model path in the STR rsrc
  873.     if( selectedCell.v < (**gGlobals).numberOfPorts ) {
  874.         printerString = GetLastSelectedUSBPrinter();
  875.         (**printerString) = 0;
  876.         ChangedResource( printerString );
  877.         SetConnectionType( kSerial );
  878.         WriteResource(printerString);
  879.     } else {
  880.         SaveSelectedUSBPrinter( selectedCell, list );
  881.     }
  882.  
  883.     // save the name of the printer
  884.     SaveSelectedPrinterName( selectedCell, list );
  885.     return noErr;
  886. }
  887.  
  888. /*-----------------------------------------------------------------------------*
  889.  
  890.     InitPack
  891.     
  892.     Desc:        Creates our global storage and reads info out of our
  893.                 connection info rsrc
  894.  
  895.     In:            None
  896.  
  897.     Out:        OS error if any
  898.     
  899.     History:
  900.     
  901.     8  May 98    gp        If we don't support USB then no need to init the name registry
  902.                         ptrs. This will prevent the name registry alert from
  903.                         displaying on non PCI PowerMacs if we only support serial.
  904.     8  May 98    gp        Moved creation of model index to here from InitGlobalStorage
  905.     21 Apr 98    gp        If we don't support serial set numberOfPorts to zero
  906.     27 Mar 98    gp        Created
  907.  
  908.  *-----------------------------------------------------------------------------*/
  909. OSErr    InitPack(void)
  910. {
  911.     OSErr                returnValue            = noErr;    // return value
  912.     USBGlobalsHandle    gGlobals            = nil;        // our global data area
  913.     ConnectionTypeHdl    connectionInfo        = nil;
  914.     short                numberOfUSBPrinters = 0;        // number of USB printers detected
  915.     short                numberOfPorts        = 0;        // number of serial ports
  916.  
  917.     // initialize our global storage
  918.     returnValue = InitGlobalStorage();
  919.     if( returnValue == noErr ) 
  920.     {
  921.         gGlobals = GetGlobalStorage();
  922.         connectionInfo = (ConnectionTypeHdl) Get1Resource( kConnectionType, kConnectionTypeID );
  923.         if( connectionInfo != nil )
  924.         {
  925.             (**gGlobals).supportsSerial = ( (**connectionInfo).supportsSerial == 1 );
  926.             (**gGlobals).supportsUSB = ( (**connectionInfo).supportsUSB == 1 );
  927.  
  928.             // if we don't support serial ports then zero out serial port count
  929.             if( (**gGlobals).supportsSerial == false )
  930.                 (**gGlobals).numberOfPorts = 0;
  931.         }
  932.         
  933.         // count USB printers
  934.         if( (**gGlobals).supportsUSB == true )
  935.         {
  936.             // if we support USB we need to init proc ptrs before calling CountUSBPrinters
  937.             InitNameRegistryPtrs();
  938.  
  939.             numberOfUSBPrinters = CountUSBPrinters();
  940.             (**gGlobals).numberOfUSBPrinters = numberOfUSBPrinters;
  941.         } else {
  942.             numberOfUSBPrinters = 0;
  943.             (**gGlobals).numberOfUSBPrinters = 0;
  944.         }
  945.  
  946.         // count serial ports
  947.         if( (**gGlobals).supportsSerial == true ) {
  948.             numberOfPorts = CountSerialPorts();
  949.             (**gGlobals).numberOfPorts = numberOfPorts;
  950.         } else {
  951.             numberOfPorts = 0;
  952.             (**gGlobals).numberOfPorts = 0;
  953.         }
  954.  
  955.         // allocate our index storage
  956.         // there is index space for serial ports which are unused but make the code simpler
  957.         (**gGlobals).modelIndex = (short*) NewPtr( (numberOfPorts+numberOfUSBPrinters)*sizeof(short) );
  958.         if ( (**gGlobals).modelIndex == nil )
  959.         {
  960.             // no index storage so get rid of our globals too
  961.             RemoveGlobalStorage();
  962.             returnValue = memFullErr;
  963.         }
  964.  
  965.     }
  966.     return returnValue;
  967. }
  968.  
  969. /*-----------------------------------------------------------------------------*
  970.  
  971.     Chooser
  972.     
  973.     Desc:        Routines to handle calls from the Chooser
  974.  
  975.     In:            - message from chooser
  976.                 - application id
  977.                 - additional info (varies)
  978.                 - name of the appletalk zone
  979.                 - handle to device choices ( printers )
  980.                 - additional info (varies)
  981.  
  982.     Out:        OS error if any
  983.     
  984.     History:
  985.     
  986.     19 Mar 98    gp        Created
  987.  
  988.  *-----------------------------------------------------------------------------*/
  989. pascal    OSErr    Chooser (short message, short caller, StringPtr objName, StringPtr zoneName, long p1, long p2)
  990. {
  991.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  992.     OSErr returnValue = noErr;                // return value
  993.  
  994.     gGlobals = GetGlobalStorage();
  995.     switch (message)
  996.     {
  997.         case chooserInitMsg:
  998.             returnValue = InitPack();
  999.             break;
  1000.         case fillListMsg:
  1001.             if( gGlobals != nil )
  1002.                 FillPrinterList( (ListHandle) p1 );
  1003.             break;
  1004.         case getSelMsg:
  1005.             if( gGlobals != nil )
  1006.                 ShowSelection ( (ListHandle)p1, zoneName);
  1007.             break;
  1008.         case selectMsg:
  1009.             if( gGlobals != nil )
  1010.                 Select ( (ListHandle)p1, zoneName, p2);
  1011.             break;
  1012.         case buttonMsg:
  1013.             break;
  1014.         case terminateMsg:
  1015.             RemoveNameRegistryPtrs();
  1016.             RemoveGlobalStorage();
  1017.             break;
  1018.         case deselectMsg:
  1019.             break;
  1020.         default:
  1021.             break;
  1022.     }
  1023.     return returnValue;
  1024. }
  1025.  
  1026. /*-----------------------------------------------------------------------------*
  1027.  
  1028.     InitGlobalStorage
  1029.     
  1030.     Desc:        Creates and stores a block of memory in our rsrc to be
  1031.                 used as global storage
  1032.  
  1033.     In:            none
  1034.  
  1035.     Out:        OS error if any
  1036.     
  1037.     History:
  1038.     
  1039.     10 Jun 98    gp        Lock our global area
  1040.     9  Jun 98    gp        Clear the handle when creating the global storage
  1041.                         Remove old global rsrc if its still there
  1042.     8  May 98    gp        Moved creation of model index to InitPack
  1043.     25 Mar 98    gp        Created
  1044.  
  1045.  *-----------------------------------------------------------------------------*/
  1046. OSErr    InitGlobalStorage(void)
  1047. {
  1048.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1049.     Handle    globalrsrc;                        // handle to store our global data address
  1050.  
  1051.     // get rid of old global rsrc if its still there
  1052.     globalrsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1053.     if( globalrsrc != nil ) {
  1054.         RemoveResource( globalrsrc );
  1055.         DisposeHandle( globalrsrc );
  1056.     }
  1057.  
  1058.     // allocate our global storage
  1059.     gGlobals = (USBGlobalsHandle) NewHandleClear( sizeof( USBGlobals ) );
  1060.     globalrsrc = NewHandleClear( sizeof( Handle ) );
  1061.     if (gGlobals != nil) 
  1062.     {
  1063.         HLockHi( (Handle) gGlobals );
  1064.         // save our global handle address in our rsrc
  1065.         (** (Handle**) globalrsrc) = (char**) gGlobals;
  1066.         addresource( globalrsrc, kGlobalType, kGlobalID,(char*) "\p");
  1067.  
  1068.         return noErr;
  1069.     } else
  1070.         return memFullErr;
  1071. }
  1072.  
  1073. /*-----------------------------------------------------------------------------*
  1074.  
  1075.     GetGlobalStorage
  1076.     
  1077.     Desc:        Retrieves our global stoarge area
  1078.  
  1079.     In:            none
  1080.  
  1081.     Out:        Handle to our global storage
  1082.     
  1083.     History:
  1084.     
  1085.     25 Mar 98    gp        Created
  1086.  
  1087.  *-----------------------------------------------------------------------------*/
  1088. USBGlobalsHandle    GetGlobalStorage(void)
  1089. {
  1090.     Handle    ourRsrc=nil;                    // handle to ourselves
  1091.  
  1092.     ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1093.     if( ourRsrc == nil )
  1094.         return nil;
  1095.     
  1096.     return (**(USBGlobalsHandle**)ourRsrc);
  1097. }
  1098.  
  1099. /*-----------------------------------------------------------------------------*
  1100.  
  1101.     RemoveGlobalStorage
  1102.     
  1103.     Desc:        Removes our global storage area
  1104.  
  1105.     In:            none
  1106.  
  1107.     Out:        Handle to our global storage
  1108.     
  1109.     History:
  1110.     
  1111.     9  Jun 98    gp        Dispose of our global rsrc after removing it
  1112.     26 Mar 98    gp        Release model index storage
  1113.     25 Mar 98    gp        Created
  1114.  
  1115.  *-----------------------------------------------------------------------------*/
  1116. void    RemoveGlobalStorage(void)
  1117. {
  1118.     USBGlobalsHandle    gGlobals=nil;        // our global data area
  1119.     Handle                ourRsrc;
  1120.     
  1121.     gGlobals = GetGlobalStorage();
  1122.     if( gGlobals != nil ) {
  1123.         // dispose of index ptr
  1124.         
  1125.         if ( (**gGlobals).modelIndex != nil )
  1126.         {
  1127.             DisposePtr( (Ptr) (**gGlobals).modelIndex );
  1128.         }
  1129.              
  1130.         // remove our global handle
  1131.         HUnlock( (Handle) gGlobals );
  1132.         DisposeHandle( (Handle) gGlobals );
  1133.         // remove our rsrc for global address storage
  1134.         ourRsrc = (Handle) Get1Resource(kGlobalType, kGlobalID);
  1135.         RemoveResource( ourRsrc );
  1136.         DisposeHandle( ourRsrc );
  1137.     }
  1138. }
  1139. // eof
  1140.